package com.xyht.sca_s.student_manage_system.modules.leave.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xyht.sca_s.student_manage_system.common.commonReturn.CommonCodeEnum;
import com.xyht.sca_s.student_manage_system.common.commonReturn.CommonResult;
import com.xyht.sca_s.student_manage_system.common.commonReturn.ExceptionCast;
import com.xyht.sca_s.student_manage_system.common.commonReturn.ResponseResult;
import com.xyht.sca_s.student_manage_system.modules.leave.entity.SmsLeave;
import com.xyht.sca_s.student_manage_system.modules.leave.entity.SmsLeaveProcess;
import com.xyht.sca_s.student_manage_system.modules.leave.entity.SmsLeaveProcessLevel;
import com.xyht.sca_s.student_manage_system.modules.leave.entity.req.SmsLeaveProcessLevelReq;
import com.xyht.sca_s.student_manage_system.modules.leave.entity.req.SmsLeaveProcessReq;
import com.xyht.sca_s.student_manage_system.modules.leave.entity.req.SmsLeaveProcessUpdateReq;
import com.xyht.sca_s.student_manage_system.modules.leave.entity.resp.SmsLeaveProcessLevelResp;
import com.xyht.sca_s.student_manage_system.modules.leave.entity.resp.SmsLeaveProcessResp;
import com.xyht.sca_s.student_manage_system.modules.leave.mapper.SmsLeaveMapper;
import com.xyht.sca_s.student_manage_system.modules.leave.mapper.SmsLeaveProcessLevelMapper;
import com.xyht.sca_s.student_manage_system.modules.leave.mapper.SmsLeaveProcessMapper;
import com.xyht.sca_s.student_manage_system.modules.leave.service.SmsLeaveProcessService;
import com.xyht.sca_s.student_manage_system.modules.user.entity.SmsRole;
import com.xyht.sca_s.student_manage_system.modules.user.mapper.SmsRoleMapper;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import static com.xyht.sca_s.student_manage_system.common.util.ParamCheckUtil.isNullOrEmpty;
import static com.xyht.sca_s.student_manage_system.modules.leave.constant.LeaveAllowFlag.ALLOW_FLAG_WAIT;

/**
 * <p>
 * 请假流程设置 服务实现类
 * </p>
 *
 * @author XYHT
 * @since 2022-12-06
 */
@Service
public class SmsLeaveProcessServiceImpl extends ServiceImpl<SmsLeaveProcessMapper, SmsLeaveProcess> implements SmsLeaveProcessService {
    @Autowired
    private SmsLeaveProcessMapper smsLeaveProcessMapper;
    @Autowired
    private SmsLeaveProcessLevelMapper smsLeaveProcessLevelMapper;
    @Autowired
    private SmsRoleMapper smsRoleMapper;
    @Autowired
    private SmsLeaveMapper smsLeaveMapper;

    @Override
    @Transactional
    public ResponseResult addLeaveProcess(SmsLeaveProcessReq smsLeaveProcessReq) {
        if (isNullOrEmpty(smsLeaveProcessReq.getProcessName()) || isNullOrEmpty(smsLeaveProcessReq.getStartHour())
                || isNullOrEmpty(smsLeaveProcessReq.getEndHour())) {
            return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
        }
        List<SmsLeaveProcessLevelReq> levelList = smsLeaveProcessReq.getLevelList();
        if (levelList == null || levelList.size() < 1) {
            return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
        }
        for (SmsLeaveProcessLevelReq leaveProcessLevelReq : levelList) {
            if (isNullOrEmpty(leaveProcessLevelReq.getRoleId()) || isNullOrEmpty(leaveProcessLevelReq.getSort())) {
                return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
            }
        }

        //校验时间段
        if (smsLeaveProcessReq.getStartHour()>smsLeaveProcessReq.getEndHour()){
            return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
        }

        int processSort;

        //流程名查重
        QueryWrapper<SmsLeaveProcess> nameQueryWrapper = new QueryWrapper<>();
        nameQueryWrapper.lambda().eq(SmsLeaveProcess::getProcessName, smsLeaveProcessReq.getProcessName());
        List<SmsLeaveProcess> nameList = smsLeaveProcessMapper.selectList(nameQueryWrapper);
        if (nameList != null && nameList.size() > 0) {
            return CommonResult.failed(CommonCodeEnum.LEAVE_PROCESS_NAME_EXIST);
        }

        //范围时间校验
        QueryWrapper<SmsLeaveProcess> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().orderByDesc(SmsLeaveProcess::getProcessSort);
        List<SmsLeaveProcess> list = smsLeaveProcessMapper.selectList(queryWrapper);
        Map<String, Object> map = new HashMap<>();
        if (list != null && list.size() > 0) {
            SmsLeaveProcess smsLeaveProcess = list.get(0);
            if (!smsLeaveProcessReq.getStartHour().equals(smsLeaveProcess.getEndHour())) {
                return CommonResult.failed(CommonCodeEnum.START_END_HOUR_ERR);
            }
            processSort = list.size() + 1;
        } else {
            if (!smsLeaveProcessReq.getStartHour().equals(0)) {
                return CommonResult.failed(CommonCodeEnum.START_END_HOUR_ERR);
            }
            processSort = 1;
        }

        //请假流程添加
        SmsLeaveProcess addSmsLeaveProcess = new SmsLeaveProcess();
        BeanUtils.copyProperties(smsLeaveProcessReq, addSmsLeaveProcess);
        addSmsLeaveProcess.setProcessSort(processSort);
        smsLeaveProcessMapper.insert(addSmsLeaveProcess);

        String process_id = addSmsLeaveProcess.getId();
        if (isNullOrEmpty(process_id)) {
            ExceptionCast.cast(CommonResult.failed(CommonCodeEnum.FAIL));
        }

        //请假流程分级表添加
        for (SmsLeaveProcessLevelReq leaveProcessLevelReq : levelList) {
            SmsRole smsRole = smsRoleMapper.selectById(leaveProcessLevelReq.getRoleId());
            if (smsRole == null) {
                ExceptionCast.cast(CommonResult.failed(CommonCodeEnum.ROLE_NOT_EXIST));
            }
            SmsLeaveProcessLevel leaveProcessLevel = new SmsLeaveProcessLevel();
            BeanUtils.copyProperties(leaveProcessLevelReq, leaveProcessLevel);
            leaveProcessLevel.setProcessId(process_id);
            smsLeaveProcessLevelMapper.insert(leaveProcessLevel);
        }
        return CommonResult.success();
    }

    @Override
    public ResponseResult applyLeaveProcess() {
        QueryWrapper<SmsLeaveProcess> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().orderByDesc(SmsLeaveProcess::getProcessSort);
        List<SmsLeaveProcess> list = smsLeaveProcessMapper.selectList(queryWrapper);
        Map<String, Object> map = new HashMap<>();
        if (list != null && list.size() > 0) {
            SmsLeaveProcess smsLeaveProcess = list.get(0);
            map.put("start_hour", smsLeaveProcess.getEndHour());
        } else {
            map.put("start_hour", 0);
        }
        return CommonResult.success(map);
    }

    @Override
    public ResponseResult updateLeaveProcess(SmsLeaveProcessUpdateReq smsLeaveProcessUpdateReq) {
        if (isNullOrEmpty(smsLeaveProcessUpdateReq.getId()) || isNullOrEmpty(smsLeaveProcessUpdateReq.getProcessSort())
        || isNullOrEmpty(smsLeaveProcessUpdateReq.getProcessName()) || isNullOrEmpty(smsLeaveProcessUpdateReq.getStartHour())
        || isNullOrEmpty(smsLeaveProcessUpdateReq.getEndHour())){
            return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
        }

        List<SmsLeaveProcessLevelReq> levelList = smsLeaveProcessUpdateReq.getLevelList();
        if (levelList == null || levelList.size() < 1) {
            return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
        }
        for (SmsLeaveProcessLevelReq leaveProcessLevelReq : levelList) {
            if (isNullOrEmpty(leaveProcessLevelReq.getRoleId()) || isNullOrEmpty(leaveProcessLevelReq.getSort())) {
                return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
            }
        }

        SmsLeaveProcess process = smsLeaveProcessMapper.selectById(smsLeaveProcessUpdateReq.getId());
        if (process == null) {
            return CommonResult.failed(CommonCodeEnum.LEAVE_PROCESS_NOT_EXIST);
        }

        if (!process.getProcessSort().equals(smsLeaveProcessUpdateReq.getProcessSort())){
            return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
        }

        //判断流程名是都重复
        if (!process.getProcessName().equals(smsLeaveProcessUpdateReq.getProcessName())){
            QueryWrapper<SmsLeaveProcess> nameQueryWrapper = new QueryWrapper<>();
            nameQueryWrapper.lambda().eq(SmsLeaveProcess::getProcessName, smsLeaveProcessUpdateReq.getProcessName());
            List<SmsLeaveProcess> nameList = smsLeaveProcessMapper.selectList(nameQueryWrapper);
            if (nameList != null && nameList.size() > 0) {
                return CommonResult.failed(CommonCodeEnum.LEAVE_PROCESS_NAME_EXIST);
            }
        }

        //判断时间段有效性
        if (!process.getStartHour().equals(smsLeaveProcessUpdateReq.getStartHour())){
            return CommonResult.failed(CommonCodeEnum.LEAVE_PROCESS_UPDATE_START_HOUR_ERR);
        }
        if (!process.getEndHour().equals(smsLeaveProcessUpdateReq.getEndHour())){
            QueryWrapper<SmsLeaveProcess> processQueryWrapper = new QueryWrapper<>();
            processQueryWrapper.lambda().gt(SmsLeaveProcess::getProcessSort,process.getProcessSort());
            List<SmsLeaveProcess> processList = smsLeaveProcessMapper.selectList(processQueryWrapper);
            if (processList != null && processList.size()>0){
                return CommonResult.failed(CommonCodeEnum.LEAVE_PROCESS_CONNECTED);
            }
        }

        SmsLeaveProcess updateProcess = new SmsLeaveProcess();
        BeanUtils.copyProperties(smsLeaveProcessUpdateReq,updateProcess);
        smsLeaveProcessMapper.updateById(updateProcess);

        //请假流程分级表添加
        QueryWrapper<SmsLeaveProcessLevel> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(SmsLeaveProcessLevel::getProcessId,process.getId());
        smsLeaveProcessLevelMapper.delete(queryWrapper);

        for (SmsLeaveProcessLevelReq leaveProcessLevelReq : levelList) {
            SmsRole smsRole = smsRoleMapper.selectById(leaveProcessLevelReq.getRoleId());
            if (smsRole == null) {
                return CommonResult.failed(CommonCodeEnum.ROLE_NOT_EXIST);
            }
            SmsLeaveProcessLevel leaveProcessLevel = new SmsLeaveProcessLevel();
            BeanUtils.copyProperties(leaveProcessLevelReq, leaveProcessLevel);
            leaveProcessLevel.setProcessId(process.getId());
            smsLeaveProcessLevelMapper.insert(leaveProcessLevel);
        }
        return CommonResult.success();
    }

    @Override
    @Transactional
    public ResponseResult deleteLeaveProcess(SmsLeaveProcess smsLeaveProcess) {
        if (isNullOrEmpty(smsLeaveProcess.getId())){
            return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
        }
        SmsLeaveProcess process = smsLeaveProcessMapper.selectById(smsLeaveProcess.getId());
        if (process == null) {
            return CommonResult.failed(CommonCodeEnum.LEAVE_PROCESS_NOT_EXIST);
        }

        //判断流程是否使用中
        QueryWrapper<SmsLeave> leaveQueryWrapper = new QueryWrapper<>();
        leaveQueryWrapper.lambda().eq(SmsLeave::getProcessId,process.getId())
                                  .eq(SmsLeave::getIsAllow,ALLOW_FLAG_WAIT);
        List<SmsLeave> leaveList = smsLeaveMapper.selectList(leaveQueryWrapper);
        if (leaveList != null && leaveList.size()>0){
            return CommonResult.failed(CommonCodeEnum.LEAVE_PROCESS_OCCUPIED);
        }

        //判断流程是否有连接流程
        QueryWrapper<SmsLeaveProcess> processQueryWrapper = new QueryWrapper<>();
        processQueryWrapper.lambda().gt(SmsLeaveProcess::getProcessSort,process.getProcessSort());
        List<SmsLeaveProcess> processList = smsLeaveProcessMapper.selectList(processQueryWrapper);
        if (processList != null && processList.size()>0){
            return CommonResult.failed(CommonCodeEnum.LEAVE_PROCESS_CONNECTED);
        }

        //删除流程
        smsLeaveProcessMapper.deleteById(process.getId());
        QueryWrapper<SmsLeaveProcessLevel> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(SmsLeaveProcessLevel::getProcessId,process.getId());
        smsLeaveProcessLevelMapper.delete(queryWrapper);
        return CommonResult.success();
    }

    @Override
    public ResponseResult getLeaveProcess(Integer pageSize, Integer pageNum) {
        QueryWrapper<SmsLeaveProcess> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().orderByAsc(SmsLeaveProcess::getProcessSort);

        Page<SmsLeaveProcess> page = new Page<>(pageNum, pageSize);
        smsLeaveProcessMapper.selectPage(page, queryWrapper);
        List<SmsLeaveProcess> list = page.getRecords();
        int total = (int) page.getTotal();
        List<SmsLeaveProcessResp> respList = new ArrayList<>();
        if (list != null && list.size() > 0) {
            for (SmsLeaveProcess smsLeaveProcess : list) {
                SmsLeaveProcessResp smsLeaveProcessResp = new SmsLeaveProcessResp();
                BeanUtils.copyProperties(smsLeaveProcess, smsLeaveProcessResp);
                respList.add(smsLeaveProcessResp);
            }
        }
        return CommonResult.success(respList,total);
    }

    @Override
    public ResponseResult getLeaveProcessDetail(String process_id) {
        if (isNullOrEmpty(process_id)) {
            return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
        }

        SmsLeaveProcess smsLeaveProcess = smsLeaveProcessMapper.selectById(process_id);
        if (smsLeaveProcess == null) {
            return CommonResult.failed(CommonCodeEnum.LEAVE_PROCESS_NOT_EXIST);
        }

        QueryWrapper<SmsLeaveProcessLevel> levelQueryWrapper = new QueryWrapper<>();
        levelQueryWrapper.lambda().eq(SmsLeaveProcessLevel::getProcessId, process_id)
                .orderByAsc(SmsLeaveProcessLevel::getSort);
        List<SmsLeaveProcessLevel> list = smsLeaveProcessLevelMapper.selectList(levelQueryWrapper);
        List<SmsLeaveProcessLevelResp> levelRespList = new ArrayList<>();
        if (list != null && list.size() > 0){
            for (SmsLeaveProcessLevel level:list){
                SmsLeaveProcessLevelResp levelResp = new SmsLeaveProcessLevelResp();
                BeanUtils.copyProperties(level,levelResp);
                levelRespList.add(levelResp);
            }
        }
        SmsLeaveProcessResp processResp = new SmsLeaveProcessResp();
        BeanUtils.copyProperties(smsLeaveProcess,processResp);
        processResp.setLevelList(levelRespList);
        return CommonResult.success(processResp);
    }

    @Override
    public ResponseResult getTotalHour() {
        List<SmsLeaveProcess> list = smsLeaveProcessMapper.selectList(new QueryWrapper<SmsLeaveProcess>()
                .lambda().orderByDesc(SmsLeaveProcess::getEndHour));
        if (list.size()<1){
            return CommonResult.failed(CommonCodeEnum.LEAVE_PROCESS_NOT_EXIST);
        }
        Integer endHour = list.get(0).getEndHour();
        if (endHour == null){
            return CommonResult.failed(CommonCodeEnum.LEAVE_PROCESS_NOT_EXIST);
        }
        return CommonResult.success(endHour);
    }
}
